package com.sudo.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

public class LocalDateTimeUtil {

    public final static String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
    public final static String yyyy_MM_dd_HH_mm_ss_SSS = "yyyy-MM-dd HH:mm:ss.SSS";

    public final static String yyyy_MM_dd = "yyyy-MM-dd";

    public final static String HH_mm_ss = "HH:mm:ss";

    public final static String yyyyMMddHHmmss = "yyyyMMddHHmmss";
    public final static String yyyyMMdd_HHmmss = "yyyyMMdd-HHmmss";

    public final static String yyyyMMddHHmmssSSS = "yyyyMMddHHmmssSSS";
    public final static String SSSssmmHHddMMyyyy = "SSSssmmHHddMMyyyy";
    public final static String yyyyMMdd_HHmmss_SSS = "yyyyMMdd_HHmmss_SSS";

    public static String convertNowTime2Str(String format){
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.now().format(dateTimeFormatter);
    }

    public static String convertLocateDateTime2Str(LocalDateTime localDateTime,String format){
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        return localDateTime.format(dateTimeFormatter);
    }

    public static LocalDateTime convertStr2LocateDateTime(String dateTimeStr,String format){
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.parse(dateTimeStr, dateTimeFormatter);
    }

    public static String convertLocateDate2Str(LocalDate localDate,String format){
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        return localDate.format(dateTimeFormatter);
    }

    public static LocalDate convertStr2LocateDate(String dateStr,String format){
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        return LocalDate.parse(dateStr, dateTimeFormatter);
    }

    public static String convertLocateTime2Str(LocalTime localTime,String format){
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        return localTime.format(dateTimeFormatter);
    }

    public static String getStandardDateTimeStr() {
        return convertLocateDateTime2Str(LocalDateTime.now(), yyyy_MM_dd_HH_mm_ss);
    }

    public static String getStandardTimeStr() {
        return convertLocateTime2Str(LocalTime.now(), HH_mm_ss);
    }

    public static String getStandardDateStr() {
        return convertLocateDate2Str(LocalDate.now(), yyyy_MM_dd);
    }

    public static String getStandardTimeStamp() {
        return convertLocateDateTime2Str(LocalDateTime.now(), yyyyMMddHHmmssSSS);
    }
    public static String getReverseTimeStamp() {
        return convertLocateDateTime2Str(LocalDateTime.now(), SSSssmmHHddMMyyyy);
    }

    // 获取当前日期月份的第一天
    public static LocalDate parseMonthBegin(int year, int month) {
        return LocalDate.of(year, month, 1);
    }

    // 根据日期获取所在月份的第一天
    public static LocalDate parseMonthBegin(LocalDate localDate) {
        return localDate.with(TemporalAdjusters.firstDayOfMonth());
    }

    // 根据日期获取所在月份的最后一天
    public static LocalDate parseMonthEnd(LocalDate localDate) {
        return localDate.with(TemporalAdjusters.lastDayOfMonth());
    }

    // 获取当前日期月份的最后一天
    public static LocalDate parseMonthEnd(int year, int month) {
        return LocalDate.of(year, month, 1).with(TemporalAdjusters.lastDayOfMonth());
    }

    public static String calculateDayHourMin(LocalDateTime ldt1, LocalDateTime ldt2) {
        long days = ldt1.until(ldt2, ChronoUnit.DAYS);
        LocalDateTime daysAfter = ldt1.plusDays(days);
        long hours = daysAfter.until(ldt2, ChronoUnit.HOURS);
        long minutes = daysAfter.plusHours(hours).until(ldt2, ChronoUnit.MINUTES);
        return days+"天"+hours+"时"+minutes+"分";
    }

    /**
     * @Description: 判断字符串日期是否匹配指定的格式化日期
     */
    public static boolean isValidDate(String strDate, String formatter) {
        SimpleDateFormat sdf = null;
        ParsePosition pos = new ParsePosition(0);

        if (StringUtils.isBlank(strDate) || StringUtils.isBlank(formatter)) {
            return false;
        }
        try {
            sdf = new SimpleDateFormat(formatter);
            sdf.setLenient(false);
            Date date = sdf.parse(strDate, pos);
            if (date == null) {
                return false;
            } else {
                if (pos.getIndex() > sdf.format(date).length()) {
                    return false;
                }
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 一周的第一天
     *
     * @param localDate 当地日期
     * @return {@link LocalDate}
     */
    public static LocalDate firstDayOfWeek(LocalDate localDate){
        return localDate.with(DayOfWeek.MONDAY);
    }

    /**
     * 一周的最后一天
     *
     * @param localDate 当地日期
     * @return {@link LocalDate}
     */
    public static LocalDate lastDayOfWeek(LocalDate localDate){
        return localDate.with(DayOfWeek.SUNDAY);
    }

    /**
     * 月的第一天
     *
     * @param localDate 当地日期
     * @return {@link LocalDate}
     */
    public static LocalDate firstDayOfMonth(LocalDate localDate){
        return localDate.with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 月的最后一天
     *
     * @param localDate 当地日期
     * @return {@link LocalDate}
     */
    public static LocalDate lastDayOfMonth(LocalDate localDate){
        return localDate.with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * 每年的第一天
     *
     * @param localDate 当地日期
     * @return {@link LocalDate}
     */
    public static LocalDate firstDayOfYear(LocalDate localDate){
        return localDate.with(TemporalAdjusters.firstDayOfYear());
    }

    /**
     * 每年的最后一天
     *
     * @param localDate 当地日期
     * @return {@link LocalDate}
     */
    public static LocalDate lastDayOfYear(LocalDate localDate){
        return localDate.with(TemporalAdjusters.lastDayOfYear());
    }


    /**
     * 每周的所有日期  即周一到周日
     *
     * @param localDate 当地日期
     * @return {@link List<LocalDate>}
     */
    public static List<LocalDate> allDaysOfWeek(LocalDate localDate){
        List<LocalDate> allDays=new ArrayList<>();
        allDays.add(localDate.with(DayOfWeek.MONDAY));
        allDays.add(localDate.with(DayOfWeek.TUESDAY));
        allDays.add(localDate.with(DayOfWeek.WEDNESDAY));
        allDays.add(localDate.with(DayOfWeek.THURSDAY));
        allDays.add(localDate.with(DayOfWeek.FRIDAY));
        allDays.add(localDate.with(DayOfWeek.SATURDAY));
        allDays.add(localDate.with(DayOfWeek.SUNDAY));
        return allDays;
    }

    /**
     * 每月的所有日期  即1日到31日
     *
     * @param localDate 当地日期
     * @return {@link List<LocalDate>}
     */
    public static List<LocalDate> allDaysOfMonth(LocalDate localDate){
        List<LocalDate> allDays=new ArrayList<>();
        LocalDate firstDayOfMonth = firstDayOfMonth(localDate);
        LocalDate lastDayOfMonth = lastDayOfMonth(localDate);
        allDays.add(firstDayOfMonth);
        int i = 1;
        LocalDate temp = firstDayOfMonth;
        while (!temp.isEqual(lastDayOfMonth)){
            LocalDate day = firstDayOfMonth.plusDays(i);
            allDays.add(day);
            temp=day;
            i++;
        }
        return allDays;
    }


    public static List<LocalDate> getDateList(LocalDate localDate, int from, int to, String unit) {
        if (from > to){
            return null;
        }
        List<LocalDate> localDateList = new ArrayList<>();
        switch (unit) {
            case "day":
                for (int i=from;i<=to;i++) {
                    LocalDate dayLocalDate = localDate.plusDays(i);
                    localDateList.add(dayLocalDate);
                }
                break;
            case "week":
                for (int i=from;i<=to;i++){
                    LocalDate weekLocalDate = localDate.plusWeeks(i);
                    localDateList.addAll(allDaysOfWeek(weekLocalDate));
                }

                break;
            case "month":
                for (int i=from;i<=to;i++){
                    LocalDate monthLocalDate = localDate.plusMonths(i);
                    localDateList.addAll(allDaysOfMonth(monthLocalDate));
                }
                break;
        }
        return localDateList;
    }

    public static void main(String[] args) {
        List<LocalDate> week = getDateList(LocalDate.now(), -2, -1, "week");
        LocalDate localDate1 = week.stream().min(Comparator.naturalOrder()).get();
        System.out.println("localDate1 = " + localDate1);
    }
}
